package controllers

import (
	"fly/global"
	"fly/helper"
	"fly/models"
	"fly/req"
	"fly/resp"
	"fly/schema"
	"fly/service"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"github.com/duke-git/lancet/v2/convertor"
	"github.com/duke-git/lancet/v2/cryptor"
	"net/url"
)

// SysUserController 系统用户
type SysUserController struct {
	BaseController
	SysUserService     service.SysUserService
	SysRoleUserService service.SysRoleUserService
}

// AddSysUser ...
// @Title 添加用户
// @Description 添加一个系统配置-用户
// @Param token header  string	false "授权Token"
// @Param body body req.AddSysUser true "添加用户数据"
// @Success 200 {object} resp.SysUserResp
// @router /save [post]
func (c *SysUserController) AddSysUser() {
	con := req.AddSysUser{}
	c.CheckReqErrorAbort(c.BindJSON(&con))
	c.ValidReqParams(&con)
	mSysUser := models.SysUser{}
	c.CheckRespErrorAbort(helper.CopyDeep(&mSysUser, con))
	id := con.Id
	var err error
	if con.Id > 0 {
		old, _ := models.GetSysUserById(con.Id)
		c.CheckReqErrorAbort(helper.RequireTrue(old != nil, "未找到资源"))
		_ = helper.CopyOut(old, con)
		if len(con.Password) > 0 {
			old.Password = cryptor.Sha1(con.Password)
		}
		err = models.UpdateSysUserById(old, c.GetReqUserId())
	} else {
		c.CheckRespErrorAbort(helper.RequireTrue(len(con.Password) >= 6, "密码长度不能小于6"))
		mSysUser.Password = cryptor.Sha1(con.Password)
		id, err = models.AddSysUser(&mSysUser, c.GetReqUserId())
	}
	err = c.SysRoleUserService.SaveOrUpdate(id, con.RoleIdList, c.GetReqUserId())
	c.CheckRespErrorAbort(err)
	_ = global.DelCache(fmt.Sprintf(service.SysUserCacheSimple, id))
	_ = global.DelCache(fmt.Sprintf(service.SysUserCacheRealName, id))
	r := resp.SysUserResp{}
	data, err := models.GetSysUserById(id)
	_ = resp.Copy2TimeResp(&r, data)
	c.Success(r)
}

// Index ...
// @Title 查询用户
// @Description 分页查询用户列表
// @Param token header  string	false "授权Token"
// @Success 200 {object} []service.Pagination
// @router / [get]
func (c *SysUserController) Index() {
	params, _ := url.ParseQuery(c.Ctx.Request.URL.RawQuery)
	data, pagination := c.SysUserService.GetPaginateData(params)
	var users []resp.SysUserResp
	c.CheckRespErrorAbort(resp.Copy2TimeResp(&users, &data))
	for i, user := range users {
		roleIdList, _ := c.SysRoleUserService.GetRoleIdListByUserId(user.Id)
		user.RoleIdList = roleIdList
		if user.DeptId != 0 {
			dept := models.SysDept{}
			_ = orm.NewOrm().QueryTable(new(models.SysDept)).Filter("id", user.DeptId).One(&dept)
			user.DeptName = dept.Name
		}
		users[i] = user
	}
	pagination.List = users
	c.Success(pagination)
}

// Detail ...
// @Title 查询用户详情
// @Description 查询用户详情
// @Param token header  string	false "授权Token"
// @Success 200 {object} resp.SysUserResp
// @router /:id [get]
func (c *SysUserController) Detail() {
	id, err := convertor.ToInt(c.Ctx.Input.Param(":id"))
	c.CheckReqErrorAbort(err)
	user, err := c.SysUserService.GetUserById(id)
	roleUser := make([]*models.SysRoleUser, 0)
	roleIds := make([]int64, 0)
	_, err = orm.NewOrm().QueryTable(new(models.SysRoleUser)).Filter("user_id", id).All(&roleUser)
	if err == nil {
		for _, role := range roleUser {
			roleIds = append(roleIds, role.RoleId)
		}
	}
	u := resp.SysUserResp{}
	c.CheckRespErrorAbort(resp.Copy2TimeResp(&u, &user))
	u.RoleIdList = roleIds
	c.Success(u)
}

// Del ...
// @Title 删除用户
// @Description 查询所有用户列表
// @Param token header  string	false "授权Token"
// @Param path id int true "用户id"
// @Success 200 {int} "id"
// @router /:id [delete]
func (c *SysUserController) Del() {
	id, err := convertor.ToInt(c.Ctx.Input.Param(":id"))
	c.CheckReqErrorAbort(err)
	c.CheckReqErrorAbort(helper.RequireTrue(c.SysUserService.IsSuperAdminUser(c.GetReqUserId()), "超级管理员才能操作"))
	c.CheckRespErrorAbort(models.DeleteSysUser(id))
	_ = global.DelCache(fmt.Sprintf(service.SysUserCacheSimple, id))
	_ = global.DelCache(fmt.Sprintf(service.SysUserCacheRealName, id))
	c.Success(id)
}

// Destroy ...
// @Title 禁用
// @Description 相当于逻辑删除
// @Param token header  string	false "授权Token"
// @Param path id int true "字典id"
// @Success 200 {int} "id"
// @router /destroy/:id [put]
func (c *SysUserController) Destroy() {
	id, err := convertor.ToInt(c.Ctx.Input.Param(":id"))
	c.CheckReqErrorAbort(err)
	c.CheckRespErrorAbort(models.DestroySysUser(id, c.GetReqUserId()))
	_ = global.DelCache(fmt.Sprintf(service.SysUserCacheSimple, id))
	_ = global.DelCache(fmt.Sprintf(service.SysUserCacheRealName, id))
	c.Success(id)
}

// Login ...
// @Title 登录
// @Description 用户名密码登录
// @Param token header  string	false "授权Token"
// @Param body body req.LoginReq true "登录数据"
// @Success 200 {object} resp.LoginResp
// @router /login [post]
func (c *SysUserController) Login() {
	loginReq := req.LoginReq{}
	c.CheckReqErrorAbort(c.BindJSON(&loginReq))
	c.ValidReqParams(&loginReq)
	user := models.SysUser{}
	err := orm.NewOrm().QueryTable(new(models.SysUser)).Filter("username", loginReq.Username).Filter("status__gte", schema.Enabled).One(&user)
	c.CheckRespErrorAbort(err)
	c.CheckReqErrorAbort(helper.RequireTrue(user.Password == cryptor.Sha1(loginReq.Password), "密码错误"))
	tokenInfo, err := c.SysUserService.GenerateToken(c.Ctx.Request.Context(), convertor.ToString(user.Id))
	c.CheckRespErrorAbort(err)
	c.Success(resp.LoginResp{
		Token:    (*tokenInfo).GetAccessToken(),
		UserId:   user.Id,
		UserName: user.Username,
		Expire:   (*tokenInfo).GetExpiresAt(),
	})
}

// UserInfo ...
// @Title 用户信息
// @Description 返回当前登录用户信息
// @Param token header  string	false "授权Token"
// @Success 200 {object} resp.SysUserResp
// @router /info [get]
func (c *SysUserController) UserInfo() {
	user, err := c.SysUserService.GetUserById(c.GetReqUserId())
	c.CheckRespErrorAbort(err)
	u := resp.SysUserResp{}
	c.CheckRespErrorAbort(resp.Copy2TimeResp(&u, &user))
	c.Success(u)
}

// UpdatePwd ...
// @Title 修改密码
// @Description 修改密码
// @Param token header  string	false "授权Token"
// @Param body body req.UpdatePwdReq true "更新数据"
// @Success 200 {int} "id"
// @router /password [put]
func (c *SysUserController) UpdatePwd() {
	con := req.UpdatePwdReq{}
	c.CheckReqErrorAbort(c.BindJSON(&con))
	c.ValidReqParams(&con)
	user, err := c.SysUserService.GetUserById(c.GetReqUserId())
	c.CheckReqErrorAbort(err)
	c.CheckReqErrorAbort(helper.RequireTrue(user.Password == cryptor.Sha1(con.Password), "原密码错误"))
	user.Password = cryptor.Sha1(con.NewPassword)
	_, err = orm.NewOrm().Update(user, "password")
	c.CheckRespErrorAbort(err)
	c.Ok()
}

// Logout ...
// @Title 登出
// @Description 退出登录
// @Param token header  string	false "授权Token"
// @Param path id int true "用户id"
// @router /logout [post]
func (c *SysUserController) Logout() {
	token := c.Ctx.Request.Header.Get(schema.TokenKey)
	err := c.SysUserService.DestroyToken(c.Ctx.Request.Context(), token)
	c.CheckRespErrorAbort(err)
	c.Ok()
}
